#ifndef _ExPrim_

   #define _ExPrim_


   #include <Windows.h>


   ////////////////////////////////////////////////////////////////////////////
   //
   // DLL Interface.
   //
   ////////////////////////////////////////////////////////////////////////////

   typedef void    (CALLBACK* ACCURRPROC)  (int From, int To, float curr_re, float curr_im);
   typedef void    (CALLBACK* DCCURRPROC)  (int From, int To, double current);
   typedef void    (CALLBACK* MSGPROC)     (const char* pcszMessage);
   typedef DWORD   (CALLBACK* PEEKPROCEX)  (int iPort, int iNumber, int iCommand);
   typedef void    (CALLBACK* POKEPROCEX)  (int iPort, int iNumber, int iCommand, DWORD dwState, float fRiseDelay, float fFallDelay);
   typedef void    (CALLBACK* TRCONDPROC)  (int InPlus, int InMinus, int From, int To, double g);
   typedef void    (CALLBACK* TRREACTPROC) (int InPlus, int InMinus, int From, int To, float g);
   typedef double* (CALLBACK* VOLTAGEPROC) (int Plus, int Minus);

   extern ACCURRPROC  pACCurrent;
   extern DCCURRPROC  pDCCurrent;
   extern MSGPROC     pfuncMessage;
   extern PEEKPROCEX  pPeekEx;
   extern POKEPROCEX  pPokeEx;
   extern TRCONDPROC  pTrConduct;
   extern TRREACTPROC pTrReact;
   extern VOLTAGEPROC pVoltage;

   #define MASK(group, select)      (group << 12) + (select)
   #define MESSAGE(pcszMessage)     (*pfuncMessage)(pcszMessage)
   #define ROF(x)                   (int)((x > 0) ? (x) + 0.5: (x) - 0.5)
   #define SET_RANGE(var, min, max) { if (var < min) var = min; else if (var > max) var = max; }

   extern double g_dVoltErr;
   extern float  g_fMaxAdmit,
                 g_fMinAdmit,
                 g_fTemp,
                 g_fTempRel,
                 g_fVtVolt;


   ////////////////////////////////////////////////////////////////////////////
   //
   // Structure:  stPrimPar
   //
   // Overview:   The structure of model's primitive. Currently it's a clone of
   //             PRIMPAR structure defined in Prim.h file.
   //
   ////////////////////////////////////////////////////////////////////////////

   typedef struct
   {
      WORD   wMask;          // Parameter level mask.
      char  *pszShortName;   // Abbreviated parameter name.
      char  *pszFullName;    // Full parameter name.
      float  flDefaultValue; // Parameter default value.
   } stPrimPar;


   ////////////////////////////////////////////////////////////////////////////
   //
   // Structure:  stPrimPin
   //
   // Overview:   The structure of model's pin.
   //
   ////////////////////////////////////////////////////////////////////////////

   typedef struct
   {
      char  *pszName; // Pin simulation name.
      int   eType,    // Pin simulation type.
            iIndex;   // Pin simulation index.
   } stPrimPin;


   ////////////////////////////////////////////////////////////////////////////
   //
   // Enumeration:   enmPrimPin
   //
   // Overview:      Lists all possible types of the pin.
   //
   ////////////////////////////////////////////////////////////////////////////

   enum enmPrimPinType
   {
      PT_NULL = 0,
      PT_IN,
      PT_OUT,
      PT_IO,
      PT_ANG
   };


   ////////////////////////////////////////////////////////////////////////////
   //
   // Structure:  stPrim
   //
   // Overview:   The base structure of the model.
   //
   ////////////////////////////////////////////////////////////////////////////

   typedef struct
   {
      char      *pszHelpFile,           // Help file name string.
                *pszHelpKey,            // Primitive help key string.
                *pszName;               // Primitive name string.
      int        iBidirect,             // Number of digital i/o pins.
                 iDataLength,           // Length of primitive work area in bytes.
                 iEntries,              // Number of analog pins.
                 iInputs,               // Number of digital input pins.
                 iInternalAnalogNodes,  // Number of internal analog nodes.
                 iInternalDigitalNodes, // Number of internal digital nodes.
                 iOutputs,              // Number of digital output pins.
                 nParams,               // Number of parameters.
                 nPins,                 // Number of pins (entries + inputs + outputs + bidirect).
                 iStatus;               // Primitive status.
      stPrimPar *pParameters;           // Primitive parameter table, size = params.
      stPrimPin *pPins;                 // Pin name table, size = pins.
   } stPrim;


   ////////////////////////////////////////////////////////////////////////////
   //
   // Primitive "status" field bit definition.
   //
   ////////////////////////////////////////////////////////////////////////////

   #define PS_INTGND     0x01 // Has internal connection to ground.
   #define PS_OVFTEST    0x02 // Iterated by linear-segment approximation.
   #define PS_MODEL      0x04 // CompValue is always a model name.
   #define PS_NONLINEAR  0x08 // Nonlinear, requires BP calc before AC sim.
   #define PS_MODEPAR    0x10 // Has grouped parameters using level mask.

   #define PI 3.141592653589

   #define ITERATE   1
   #define INTEGRATE 2
   #define AC_SIM    4

   enum
   {
      LC_NOCHG = 0,
      LC_SOLVE = 1,
      LC_CLEAR = 2,
      LC_SET = 4
   };

   #define TRANSCONDUCTANCE (*pTrConduct)
   #define TRANSREACTANCE   (*pTrReact)
   #define DC_CURRENT       (*pDCCurrent)
   #define AC_CURRENT       (*pACCurrent)
   #define CONDUCTANCE(n1, n2, y) TRANSCONDUCTANCE(n1, n2, n1, n2, y)
   #define REACTANCE(n1, n2, y) TRANSREACTANCE(n1, n2, n1, n2, y)
   #define VOLTAGE *(*pVoltage)
   #define GND_NET -1


   typedef struct
   {
      double ic,
             yc;
      float  time;
   } icap;

   typedef struct
   {
      double in,
             yn;
   } idp;

   typedef struct
   {
      float a, b, c;
      int   rev;
   } ifp;

   typedef struct
   {
      double il,
             yl;
      float  time;
   } iind;

   typedef struct
   {
      double ib,
             yb;
   } irdp;


   void  FieldEffect          (double v_ds, double v_gs, double v_gd, float vto, float beta, float lambda, int iPolarity, ifp* fptr);
   void  InitCapacitor        (icap* pCap);
   void  InitInductor         (iind* pInd);
   void  InternalDiode        (float is, float vk, float vt, double v, idp* dptr);
   void  InternalReverceDiode (float ibv, float bv, float vk, float vt, double v, irdp *dptr);
   void  MaxErr               (int iNet1, int iNet2, double* pV);
   void  MaxErrEx             (int iNet1, int iNet2, double* pV, double* pdVoltErr);
   float PN_Capacitor         (float Cjo, float TT, float M, float FC, float VJ, float Is, float Ibv, float Bv, float volt);
   void  SetCurrent           (int iPlus, int iMinus, double dCurrent);
   void  SetCapacitor         (float fVolt, icap* pCap);
   void  SetCapacitorAC       (int n1, int n2, float fCap, float fOmega);
   void  SetCapacitorDC       (int n1, int n2, float fCap, icap* pCap, float fSimTime, WORD wMode);
   void  SetInductor          (float fCurrent, iind* pInd);
   void  SetInductorAC        (int n1, int n2, float fInd, float fOmega);
   void  SetInductorDC        (int n1, int n2, float fInd, iind* pInd, float fSimTime, WORD wMode);
   void  SetMutIndAC          (int p1, int p2, int s1, int s2, float f, float fOmega);
   void  SetMutIndDC          (int p1, int p2, int s1, int s2, float f, iind* pIind, float fSimTime, WORD wMode);
   void  SetTemp              ();
   void  SetVoltage           (int iPlus, int iMinus, double dVolt);
   float Temp_brf             (float brf, float xtb);
   float Temp_cj              (float cjo, float m, float vj_div);
   float Temp_is              (float is, float n, float eg, float xti);
   float Temp_vj              (float vj);
   void  TestResist           (float fRes, float* pfMinAdmit, float* pfMaxAdmit);

   // Logic state mask.

   #define LSTATE 3

   // States.

   #define LOW    0
   #define XSTAT1 1
   #define XSTAT2 2
   #define HIGH   3

   // Logic power mask.

   #define LPOWER 0xC

   // Power values.

   #define ZIMP   0x0 
   #define XPWR1  0x4
   #define XPWR2  0x8
   #define DRV    0xC

   // Power values and states.

   #define OUT_L DRV + LOW
   #define OUT_D XPWR1 + XSTAT1
   #define OUT_X DRV + XSTAT1
   #define OUT_Z ZIMP + XSTAT1
   #define OUT_U XPWR1 + XSTAT2
   #define OUT_H DRV + HIGH

   // State triggering.

   #define CHANGE (LSTATE << 8 | LSTATE)
   #define RISE   (LOW << 8 | HIGH)
   #define FALL   (HIGH << 8 | LOW)

   // State negation.

   #define NOT(st)  (st^LSTATE)
   #define NOT2(st) (st^CHANGE)

   ////////////////////////////////////////////////////////////////////////////
   //
   //  Macros for all cases of use callback functions PEEK, POKE, SETUP:
   //  parameters:
   //    iPort   - input/output start number.
   //    iNumber - number of inputs/outputs for word functions [1-32].
   //    dwState - logic state bit or word of up to 32 logic state bits.
   //    dr      - rise delay value (float).
   //    df      - fall delay value (float).
   //
   ////////////////////////////////////////////////////////////////////////////

   #define KILL_ALARM()	                                   (*pPokeEx)(0, 0, 0xFFFF, 0, 0, 0)
   #define PEEK(iPort) 	                                   (*pPeekEx)(iPort, 0, 0)
   #define PEEK_AND(iPort, iNumber)	                       (*pPeekEx)(iPort, iNumber, 4)
   #define PEEK_AND_CHANGE(iPort, iNumber)                 (*pPeekEx)(iPort, iNumber, 5)
   #define PEEK_AND_EDGE(iPort, iNumber)                   (*pPeekEx)(iPort, iNumber, 6)
   #define PEEK_CHANGE(iPort)	                             (*pPeekEx)(iPort, 0, 1)
   #define PEEK_DWORD(iPort, iNumber)	                    (*pPeekEx)(iPort, iNumber, 12)
   #define PEEK_EDGE(iPort)	                             (*pPeekEx)(iPort, 0, 2)
   #define PEEK_OR(iPort, iNumber)	                       (*pPeekEx)(iPort, iNumber, 8)
   #define PEEK_OR_CHANGE(iPort, iNumber)                  (*pPeekEx)(iPort, iNumber, 9)
   #define PEEK_OR_EDGE(iPort, iNumber)                    (*pPeekEx)(iPort, iNumber, 10)
   #define PEEK_WORD_CHANGE(iPort, iNumber)                (*pPeekEx)(iPort, iNumber, 13)
   #define POKE_ALARM(d)	                                (*pPokeEx)(0, 0, 0xFFFF, 1, d, d)
   #define POKE_DRV(iPort, dwState, dr, df)	              (*pPokeEx)(iPort, 1, 2, dwState, dr, df)
   #define POKE_OC(iPort, dwState, dr, df)	              (*pPokeEx)(iPort, 1, 1, dwState, dr, df)
   #define POKE_WORD_DRV(iPort, iNumber, dwState, dr, df)  (*pPokeEx)(iPort, iNumber, 2, dwState, dr, df)
   #define POKE_WORD_OC(iPort, iNumber, dwState, dr, df)   (*pPokeEx)(iPort, iNumber, 1, dwState, dr, df)
   #define POKE_WORD_XPWR(iPort, iNumber, dwState, dr, df) (*pPokeEx)(iPort, iNumber, 3, dwState, dr, df)
   #define POKE_WORD_ZIMP(iPort, iNumber, dr, df)          (*pPokeEx)(iPort, iNumber, 0, 0, dr, df)
   #define POKE_XPWR(iPort, dwState, dr, df)	              (*pPokeEx)(iPort, 1, 3, dwState, dr, df)
   #define POKE_ZIMP(iPort, dr, df)	                       (*pPokeEx)(iPort, 1, 0, 0, dr, df)
   #define SETUP_DRV(iPort, dwState)	                    POKE_DRV(iPort, dwState, 0, 0)
   #define SETUP_OC(iPort, dwState)	                       POKE_OC(iPort, dwState, 0, 0)
   #define SETUP_WORD_DRV(iPort, iNumber, dwState)         POKE_WORD_DRV(iPort, iNumber, dwState, 0, 0)
   #define SETUP_WORD_OC(iPort, iNumber, dwState)          POKE_WORD_OC(iPort, iNumber, dwState, 0, 0)
   #define SETUP_WORD_ZIMP(iPort, iNumber)                 POKE_WORD_ZIMP(iPort, iNumber, 0, 0)
   #define SETUP_ZIMP(iPort)	                             POKE_ZIMP(iPort, 0, 0)

#endif
